﻿using LibBinary.FileData;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LibBinary.FileDeclaration
{
    public interface IConditionProvider
    {
        bool GetResult(AbstractFileData data);
    }

    public class ReferenceBoolConditionProvider : IConditionProvider
    {
        private readonly int index;

        public ReferenceBoolConditionProvider(int index)
        {
            this.index = index;
        }

        public bool GetResult(AbstractFileData data)
        {
            var parent = data.Parent.As<StructuredData>();

            if (parent == null || index < 0 || index >= parent.Data.Length)
            {
                throw new ReadingFormatException("Can not access condition field.");
            }
            var pri = parent.Data[index].As<SystemPrimitiveData>();
            if (pri == null || !pri.BoolData.HasValue)
            {
                throw new ReadingFormatException("Condition field does not contain a boolean.");
            }
            return pri.BoolData.Value;
        }
    }

    public enum ConditionIntCompare
    {
        Equal,
        NotEqual,
        Greater,
        GreaterEqual,
        Less,
        LessEqual,
    }

    public class ReferenceIntConditionProvider : IConditionProvider
    {
        private readonly int index;
        private readonly ConditionIntCompare method;
        private readonly int value;

        public ReferenceIntConditionProvider(int index, ConditionIntCompare method, int value)
        {
            this.index = index;
            this.method = method;
            this.value = value;
        }

        public bool GetResult(AbstractFileData data)
        {
            var parent = data.Parent.As<StructuredData>();

            if (parent == null || index < 0 || index >= parent.Data.Length)
            {
                throw new ReadingFormatException("Can not access condition field.");
            }
            var pri = parent.Data[index].As<SystemPrimitiveData>();
            if (pri == null || !pri.IntData.HasValue)
            {
                throw new ReadingFormatException("Condition field does not contain a integer to compare.");
            }
            var valueInData = pri.IntData.Value;
            switch (method)
            {
                case ConditionIntCompare.Equal:
                    return valueInData == value;
                case ConditionIntCompare.NotEqual:
                    return valueInData != value;
                case ConditionIntCompare.Greater:
                    return valueInData > value;
                case ConditionIntCompare.GreaterEqual:
                    return valueInData >= value;
                case ConditionIntCompare.Less:
                    return valueInData < value;
                case ConditionIntCompare.LessEqual:
                    return valueInData <= value;
            }
            throw new ReadingFormatException("Unknown ConditionIntCompare.");
        }
    }
}
